package com.eunion.core.common.jpa.query;

import java.util.Optional;
import java.util.function.Consumer;

import javax.persistence.criteria.Root;

import com.eunion.core.common.jpa.MatchType;
import com.eunion.core.common.query.QueryContainer;
import com.eunion.core.common.request.SortingRequest;

public final class QueryRequirements {

    public static <Entity, Bean> FindByKeyQueryRequirement<Entity, Bean> byKey(String key) {
        return new FindByKeyQueryRequirement<>(key);
    }

    public static <Entity, Bean> FindByKeyQueryRequirement<Entity, Bean> byKey(String key, String keyColumn) {
        return new FindByKeyQueryRequirement<>(key, keyColumn);
    }

    public static <Entity, Bean> FindByKeyQueryRequirement<Entity, Bean> byKey(String key,
            Consumer<Root<Entity>> fectchStrategy) {
        return new FindByKeyQueryRequirement<>(key, fectchStrategy);
    }

    public static <Entity, Bean> FindByKeyQueryRequirement<Entity, Bean> byKey(String key, String keyColumn,
            Consumer<Root<Entity>> fectchStrategy) {
        return new FindByKeyQueryRequirement<>(key, keyColumn, fectchStrategy);
    }

    public static <Entity, Bean> QuickFilterQueryRequirement<Entity, Bean> quickFilter(String quickFilter,
            String... columns) {
        return new QuickFilterQueryRequirement<>(quickFilter, columns);
    }

    public static <Entity, Bean> QuickFilterQueryRequirement<Entity, Bean> quickFilter(String quickFilter,
            MatchType matchType, String... columns) {
        return new QuickFilterQueryRequirement<>(quickFilter, matchType, columns);
    }

    public static <Entity, Bean> RequestQueryRequirement<Entity, Bean> request(
            SortingRequest<? extends QueryContainer<Entity>> request) {
        return new RequestQueryRequirement<>(Optional.ofNullable(request).map(SortingRequest::getQuery).orElse(null));
    }

    public static <Entity, Bean> RequestQueryRequirement<Entity, Bean> request(
            SortingRequest<? extends QueryContainer<Entity>> request,
            Consumer<Root<Entity>> fectchStrategy) {
        return new RequestQueryRequirement<>(
                Optional.ofNullable(request).map(SortingRequest::getQuery).orElse(null), fectchStrategy);
    }

    public static <Entity, Bean> RequestQueryRequirement<Entity, Bean> queryBean(QueryContainer<Entity> queryBean) {
        return new RequestQueryRequirement<>(queryBean);
    }

    public static <Entity, Bean> RequestQueryRequirement<Entity, Bean> queryBean(QueryContainer<Entity> queryBean,
            Consumer<Root<Entity>> fectchStrategy) {
        return new RequestQueryRequirement<>(queryBean, fectchStrategy);
    }
}
